﻿using System;
using System.Collections.Generic;
using System.Linq;
using Castle.Core.Logging;
using User.EF.Contracts;
using User.EF.Model;

namespace User.EF.Queries
{
    /// <summary>
    /// Die aktuellen Queries für die Rechteverwaltung.
    /// </summary>
    public class RightQueries : IRightQueries
    {
        #region Member
        /// <summary>
        /// Der Aktuelle context über den die Daten abgerufen werden können
        /// </summary>
        public MainModelContainer Context { get; private set; }

        /// <summary>
        /// Der Aktuelle Logger.
        /// </summary>
        public ILogger Logger { get; set; }
        #endregion

        #region Initialize
        public RightQueries(MainModelContainer context)
        {
            if (context == null)
            {
                throw  new NullReferenceException("Mainmodelcontainer is null");
            }

            Context = context;
        }
        #endregion

        #region Public Functions

        /// <summary>
        /// Speichern der Einstellungen
        /// </summary>
        /// <returns></returns>
        public bool Save()
        {
            try
            {
                Context.SaveChanges();
                return true;
            }
            catch (Exception)
            {
                return false;
            }
        }

        /// <summary>
        /// Prüft ob die Übergebene UserId das Admin Right hat.
        /// </summary>
        /// <param name="userId">Die UserId die überprüft werden soll</param>
        /// <returns>TRUE->Hat das Admin Recht | FALSE->Hat kein Admin Recht</returns>
        public bool IsAdmin(long userId)
        {
            return HasRight(userId, EMemberRight.Administrator);
        }

        /// <summary>
        /// Ermittelt Alle Rechte der übergebenen UserId
        /// </summary>
        /// <param name="userId">Die UserId für die alle Rechte ermittelt werden sollen</param>
        public List<EMemberRight> UserRights(long userId)
        {
            return Context.MemberRightsSet.Where(p => p.MemberId == userId).Select(p=>p.MemberRight).ToList();
        }

        /// <summary>
        /// Prüfen ob der User das übergebene Userrecht hat oder nicht.
        /// </summary>
        /// <param name="userId">Die UserId die überprüft werden soll</param>
        /// <param name="userRight">Das passende Recht nach dem gesucht wird.</param>
        /// <returns>TRUE->Hat das Recht | FALSE->Hat nicht das Recht</returns>
        public bool HasRight(long userId, EMemberRight userRight)
        {
            return Context.MemberRightsSet.Any(p => p.MemberId == userId && p.MemberRight == userRight);
        }

        /// <summary>
        /// Dem User das Recht zuweisen.
        /// </summary>
        /// <param name="userId">Die UserId der das Recht zugewiesen werden soll</param>
        /// <param name="userRight">Das Recht das dem User zugewiesen werden soll</param>
        public bool AddRight(long userId, EMemberRight userRight)
        {
            try
            {
                if (!Context.MemberRightsSet.Any(p => p.MemberId == userId && p.MemberRight == userRight))
                {
                    Context.MemberRightsSet.Add(new MemberRights() {MemberId = userId, MemberRight = userRight});
                    Context.SaveChanges();
                }

            }
            catch (Exception exception)
            {
                Logger.Error("Add Exception Right UserId: " + userId, exception);
                return false;
            }

            return true;
        }

        /// <summary>
        /// Das Recht vom User entfernen
        /// </summary>
        /// <param name="userId">Die UserId der das Recht entzogen werden soll</param>
        /// <param name="userRight">Das Recht welches entzogen werden soll</param>
        /// <returns>TRUE->Erfolgreich entfernt | FALSE->Fehler beim Entfernen des Rechts</returns>
        public bool RemoveRight(long userId, EMemberRight userRight)
        {
            try
            {
                //Alle Rechte für das übergebene Recht für den User ermitteln (Achtung, hier sollte immer nur eins zurückkommen, aber auf Nummer sicher gehen und alle durchgehen!)
                var rights = Context.MemberRightsSet.Where(p => p.MemberId == userId && p.MemberRight == userRight);
                foreach (var right in rights)
                {
                    Context.MemberRightsSet.Remove(right);
                }

                Context.SaveChanges();
            }
            catch (Exception exception)
            {
                Logger.Error("Remove Exception Right UserId: " + userId, exception);
                return false;
            }

            return true;
        }

        /// <summary>
        /// Hinzufügen der Standardrechte für das Vocabelmodul
        /// </summary>
        /// <param name="userId">die UserId der die Rechte hinzugefügt werden sollen</param>
        public void AddDefaultVocabelRights(long userId)
        {
            AddRight(userId, EMemberRight.VocableModule);
        }
        #endregion

    }
}
